//
//  Misc+YHExtension.swift
//  Adorbee
//
//  Created by amovision on 2024/11/26.
//

import AVKit
import UIKit

public extension Encodable {
  var keyValues: [String: Any] {
    let encoder = JSONEncoder()
    do {
      let jsonData = try encoder.encode(self)
      if let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
        return jsonObject
      }
    } catch {
      print("Error encoding or converting to dictionary: \(error)")
    }
    return [:]
  }
}

public extension AVPlayerViewController {
  convenience init(url: URL?) {
    self.init()
    if let url { player = AVPlayer(url: url) }
  }
}

public extension Selector {
  static let buttonAction = NSSelectorFromString("buttonAction:")
  static func SEL(_ sel: String) -> Selector {
    NSSelectorFromString(sel)
  }
}

public extension Comparable {
  func clamped(_ low: Self, _ high: Self) -> Self {
    return max(low, min(self, high))
  }
}

public extension BinaryInteger {
  mutating func toggle() {
    if self == 0 {
      self = 1
    } else {
      self = 0
    }
  }

  var bool: Bool { self != 0 }

  var formatTime: String {
    String(format: "%02d:%02d", Int(self) / 60, Int(self) % 60)
  }

  /// duration extension
  static func seconds<T: BinaryInteger>(_ value: T) -> T {
    value / 1_000_000_000
  }

  static func milliseconds<T: BinaryInteger>(_ value: T) -> T {
    value / 1000
  }

  static func microseconds<T: BinaryInteger>(_ value: T) -> T {
    value / 1_000_000
  }

  static func nanoseconds<T: BinaryInteger>(_ value: T) -> T {
    value / 1_000_000_000
  }
}

// 用于关联对象的 Key
private var lastExecutionTimeKey: UInt8 = 0

public extension NSObject {
  /// 检查距离上次“成功”执行是否已超过指定的时间间隔（节流）。
  ///
  /// 此方法使用 `ProcessInfo.processInfo.systemUptime`（单调时钟），
  /// 它位于 Foundation 框架中，适合作为通用的基础功能，不受系统时间变化的影响。
  ///
  /// - Parameter interval: 最小时间间隔（秒）。
  /// - Returns: `true` 如果可以执行（时间已超过间隔），`false` 如果应拦截（仍在冷却期）。
  @objc func throttle(interval: TimeInterval) -> Bool {
    let now = ProcessInfo.processInfo.systemUptime

    let lastTime = objc_getAssociatedObject(self, &lastExecutionTimeKey) as? TimeInterval

    if let lastTime = lastTime {
      let timePassed = now - lastTime

      if timePassed > interval {
        objc_setAssociatedObject(self, &lastExecutionTimeKey, now, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        return true
      } else {
        return false
      }
    } else {
      objc_setAssociatedObject(self, &lastExecutionTimeKey, now, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
      return true
    }
  }
}

public protocol YHCopyable: Codable {
  func copy() -> Self
}

public extension YHCopyable {
  func copy() -> Self {
    guard let data = try? JSONEncoder().encode(self) else {
      fatalError("copy encode error")
    }
    guard let target = try? JSONDecoder().decode(Self.self, from: data) else {
      fatalError("copy decode error")
    }
    return target
  }
}

/// Base为实际需要添加扩展的类型（比如Data, String等）
public struct YouHunWrapper<Base> {
  public let base: Base
  public init(base: Base) {
    self.base = base
  }
}

public protocol YouHunCompatiable {
  associatedtype Base
  var yh: YouHunWrapper<Base> { get }
  static var yh: YouHunWrapper<Base>.Type { get }
}

/// 添加默认实现
public extension YouHunCompatiable {
  var yh: YouHunWrapper<Self> { YouHunWrapper(base: self) }
  static var yh: YouHunWrapper<Self>.Type { YouHunWrapper<Self>.self }
}
